// 输入: s = "abcabcbb"
// 输出: 3 
// 解释: 因为无重复字符的最长子串是 "abc"，所以其长度为 3。
// 示例 2:

// 输入: s = "bbbbb"
// 输出: 1
// 解释: 因为无重复字符的最长子串是 "b"，所以其长度为 1。
// 示例 3:

// 输入: s = "pwwkew"
// 输出: 3
// 解释: 因为无重复字符的最长子串是 "wke"，所以其长度为 3。
//      请注意，你的答案必须是 子串 的长度，"pwke" 是一个子序列，不是子串。

// var lengthOfLongestSubstring = function (s) {
//   let arr = []
//   let max = 0
//   for (let i = 0; i < s.length; i++) {
//     if (arr.indexOf(s[i]) !== -1) {
//       console.log(arr.splice(0, arr.indexOf(s[i]) + 1));
//       arr.splice(0, arr.indexOf(s[i]) + 1)
//     }
//     // 获取指定位置处的字符
//     arr.push(s[i])
//     max = Math.max(arr.length, max)
//   }
//   return max
// };
// 使用 map 来存储当前已经遍历过的字符，key 为字符，value 为下标

// 使用 i 来标记无重复子串开始下标，j 为当前遍历字符下标

// 遍历字符串，判断当前字符是否已经在 map 中存在，存在则更新无重复子串开始下标 i 为相同字符的下一位置，此时从 i 到 j 为最新的无重复子串，更新 max ，将当前字符与下标放入 map 中

let lengthOfLongestSubstring = function (s) {
  let map = new Map()
  let max = 0
  for (let i = 0, j = 0; j < s.length; j++) {
    if (map.has(s[j])) {
      i = Math.max(map.get(s[j]) + 1, i)
    }
    // i为标记无重复字串开始下标j为当前遍历字符下标
    max = Math.max(max, j - i + 1)
    map.set(s[j], j)
  }
  return max
}
let s = "abcabcbb"
// let s = "bbbbb"
// let s = "pwwkew"
//map.get 得到的是value值
console.log(lengthOfLongestSubstring(s));
// const ch5F = '_'.charCodeAt(0)
// console.log(ch5F);